﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using CardTypes = Wormhole.Engine.CardLibrary.CardTypes;
using EngineGlyphs = Wormhole.Engine.Glyphs;

namespace Wormhole.UI.Application.Controls.Glyphs
{
	/// <author>Rodney McKay</author>
	/// <date>20 April 2008</date>
	/// <summary>
	/// Layout glyphs on a team character card.
	/// </summary>
	public class GlyphLayout : Grid
	{
		#region Declarations
		/// <summary>
		/// The glyphs that should be displayed.
		/// </summary>
		protected List<Glyph> glyphs = new List<Glyph>();
		#endregion

		#region Properties
	
		#region Max Space
		/// <summary>
		/// The maximum space between cards.
		/// </summary>
		public const int MAX_SPACE = 0;
		#endregion

		#region Team Card
		private CardTypes.Character _teamCard;
		/// <summary>
		/// The team card that have the glyphs on it.
		/// </summary>
		public CardTypes.Character TeamCard
		{
			get
			{
				return this._teamCard;
			}

			set
			{
				if (this._teamCard != value)
				{
					this._teamCard = value;
					this.SetEngineEvents();
				}
			}
		}
		#endregion

		#endregion

		#region Set Engine Events
		/// <summary>
		/// Wire up events from the engine object.s
		/// </summary>
		protected void SetEngineEvents()
		{
			this.TeamCard.EarnedGlyphs.ItemAdded += new Wormhole.Engine.Glyphs.EarnedGlyphs.ItemAddedDelegate(EarnedGlyphs_ItemAdded);
			this.TeamCard.EarnedGlyphs.ItemRemoved += new Wormhole.Engine.Glyphs.EarnedGlyphs.ItemRemovedDelegate(EarnedGlyphs_ItemRemoved);
		}
		#endregion

		#region Add Glyph
		/// <summary>
		/// Add a glyph to the user interface.
		/// </summary>
		/// <param name="glyph">The glyph that must be added.</param>
		protected void AddGlyph(EngineGlyphs.EarnedGlyph glyph)
		{
			// create the glyph that will be displayed
			Glyph uiGlyph = new Glyph(glyph);
			uiGlyph.Width= 27;
			uiGlyph.Height = 14;

			// add the glyph
			this.Children.Add(uiGlyph);
			this.glyphs.Add(uiGlyph);

			// do the control layout
			this.Layout();
		}
		#endregion

		#region Remove Glyph
		/// <summary>
		/// Remove a glyph from the user interface.
		/// </summary>
		/// <param name="glyph">The glyph that should be removed.</param>
		protected void RemoveGlyph(EngineGlyphs.EarnedGlyph glyph)
		{
			try
			{
				// find the ui card to remove
				Glyph uiGlyph = this.glyphs.Single(g => g.EngineGlyph.Equals(glyph));

				// remove the card
				this.Children.Remove(uiGlyph);
				this.glyphs.Remove(uiGlyph);

				// refresh the layout
				this.Layout();
			}
			catch (Exception ex)
			{
				System.Diagnostics.Trace.Fail("Card could not be removed", ex.Message);
			}
		}
		#endregion

		#region On Render Size Changed
		/// <summary>
		/// 
		/// </summary>
		/// <param name="sizeInfo"></param>
		protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
		{
			base.OnRenderSizeChanged(sizeInfo);
			this.Layout();
		}
		#endregion

		#region Layout
		/// <summary>
		/// Layout the controls.
		/// </summary>
		protected virtual void Layout()
		{
			if (this.glyphs.Count > 0)
			{
				// calculate the space required
				double glyphHeight = this.GetTotalGlyphHeight();
				double totalSpace = glyphHeight + (this.glyphs.Count - 1) * MAX_SPACE;

				// calculate the spacer width
				double spacer = MAX_SPACE;
				if (totalSpace > this.ActualHeight)
				{
					double spaceRequired = glyphHeight - this.ActualHeight;
					spacer = (spaceRequired / (this.glyphs.Count - 1)) * -1;
					totalSpace = glyphHeight + (spaceRequired * -1);
				}

				// calculate the position from the top margin
				double top = 0;

				// position the buttons
				foreach (Glyph glyph in this.glyphs)
				{
					glyph.Margin = new Thickness(0, top, 0, 0);
					glyph.HorizontalAlignment = HorizontalAlignment.Right;
					glyph.VerticalAlignment = VerticalAlignment.Top;
					top += (glyph.Height + spacer);
				}
			}
		}
		#endregion

		#region Get Total Glyph Height
		/// <summary>
		/// Get the combined height of all glyphs.
		/// </summary>
		/// <returns>Returns the combined height of the glyphs.</returns>
		protected double GetTotalGlyphHeight()
		{
			double height = 0;

			foreach (Glyph glyph in this.glyphs)
			{
				height += glyph.ActualHeight;
			}

			return height;
		}
		#endregion

		#region Event Handlers

		#region Item Added
		/// <summary>
		/// An glyph was added.
		/// </summary>
		/// <param name="glyph">The new glyph.</param>
		private void EarnedGlyphs_ItemAdded(Wormhole.Engine.Glyphs.EarnedGlyph glyph)
		{
			this.Dispatcher.Invoke(
				DispatcherPriority.Normal,
				(System.Windows.Forms.MethodInvoker)delegate()
			{
				this.AddGlyph(glyph);
			});
		}
		#endregion

		#region Item Removed
		/// <summary>
		/// A glyph was removed.
		/// </summary>
		/// <param name="glyph">The removed glyph.</param>
		private void EarnedGlyphs_ItemRemoved(Wormhole.Engine.Glyphs.EarnedGlyph glyph)
		{
			this.RemoveGlyph(glyph);
		}
		#endregion

		#endregion
	}
}
